//! # Kubernetes 集成
//!
//! 将 Kubernetes 功能与 RustCloud 的服务注册、配置管理等核心功能集成。

use crate::{
    client::KubernetesClient,
    discovery::{K8sServiceDiscovery, ServiceInfo, ServiceDiscovery},
    error::{K8sError, K8sResult},
};
use async_trait::async_trait;
use rustcloud_core::{
    ServiceInstance, ServiceRegistry, ServiceResult, ServiceError, ServiceRegistryEvent,
};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::sync::Arc;
use tracing::{debug, info};

/// 空的服务监听器实现
struct EmptyWatcher;

#[async_trait]
impl rustcloud_core::ServiceWatcher for EmptyWatcher {
    async fn next_event(&mut self) -> ServiceResult<ServiceRegistryEvent> {
        // 返回一个虚拟事件，实际实现中可以监听Kubernetes API
        tokio::time::sleep(std::time::Duration::from_secs(60)).await;
        Ok(ServiceRegistryEvent::InstanceAdded {
            service_name: "unknown".to_string(),
            instance: ServiceInstance {
                service_id: "unknown".to_string(),
                host: "localhost".to_string(),
                port: 8080,
                scheme: "http".to_string(),
                metadata: HashMap::new(),
                healthy: true,
                weight: 1.0,
                group: None,
                namespace: None,
                environment: None,
                cluster: None,
            },
        })
    }
}

/// Kubernetes 集成配置
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct K8sIntegrationConfig {
    /// 是否启用服务发现
    pub enable_service_discovery: bool,
    /// 默认命名空间
    pub default_namespace: String,
    /// 服务发现标签选择器
    pub service_selector: HashMap<String, String>,
    /// 服务同步间隔（秒）
    pub sync_interval: u64,
}

impl Default for K8sIntegrationConfig {
    fn default() -> Self {
        Self {
            enable_service_discovery: true,
            default_namespace: "default".to_string(),
            service_selector: HashMap::new(),
            sync_interval: 30,
        }
    }
}

/// Kubernetes 服务注册集成
pub struct K8sServiceRegistry {
    client: Arc<KubernetesClient>,
    discovery: Arc<K8sServiceDiscovery>,
    config: K8sIntegrationConfig,
}

impl K8sServiceRegistry {
    /// 创建新的 Kubernetes 服务注册
    pub fn new(
        client: Arc<KubernetesClient>,
        config: K8sIntegrationConfig,
    ) -> K8sResult<Self> {
        let discovery = Arc::new(K8sServiceDiscovery::new(client.clone()));
        
        Ok(Self {
            client,
            discovery,
            config,
        })
    }

    /// 将 Kubernetes Service 转换为 ServiceInstance
    fn service_to_instance(&self, service_info: &ServiceInfo) -> Vec<ServiceInstance> {
        let mut instances = Vec::new();

        for endpoint in &service_info.endpoints {
            if endpoint.ready {
                let instance = ServiceInstance {
                    service_id: format!("{}:{}:{}", service_info.name, endpoint.ip, endpoint.port),
                    host: endpoint.ip.clone(),
                    port: endpoint.port as u16,
                    scheme: "http".to_string(), // 默认使用HTTP
                    metadata: {
                        let mut metadata = service_info.labels.clone();
                        if let Some(pod_name) = &endpoint.pod_name {
                            metadata.insert("pod_name".to_string(), pod_name.clone());
                        }
                        if let Some(node_name) = &endpoint.node_name {
                            metadata.insert("node_name".to_string(), node_name.clone());
                        }
                        metadata
                    },
                    healthy: endpoint.ready,
                    weight: 1.0,
                    group: None,
                    namespace: Some(service_info.namespace.clone()),
                    environment: service_info.labels.get("environment")
                        .or_else(|| service_info.labels.get("env"))
                        .cloned(),
                    cluster: service_info.labels.get("cluster").cloned(),
                };
                instances.push(instance);
            }
        }

        instances
    }
}

#[async_trait]
impl ServiceRegistry for K8sServiceRegistry {
    async fn register(&self, instance: ServiceInstance) -> ServiceResult<()> {
        // 在 Kubernetes 环境中，服务注册通常通过 Service 和 Endpoints 资源完成
        // 这里我们记录注册请求，但实际的服务发现依赖于 Kubernetes 原生机制
        info!("Kubernetes 服务注册: {} ({}:{})", 
            instance.service_id, instance.host, instance.port);
        Ok(())
    }

    async fn deregister(&self, instance: ServiceInstance) -> ServiceResult<()> {
        info!("Kubernetes 服务注销: {} (ID: {})", instance.service_id, instance.service_id);
        Ok(())
    }

    async fn discover(&self, service_name: &str) -> ServiceResult<Vec<ServiceInstance>> {
        if !self.config.enable_service_discovery {
            return Ok(vec![]);
        }

        debug!("从 Kubernetes 发现服务: {}", service_name);

        let services = self.discovery
            .discover_services(&self.config.default_namespace)
            .await
            .map_err(|e| ServiceError::ConfigError(format!("Kubernetes 服务发现失败: {}", e)))?;

        let mut instances = Vec::new();
        
        for service in services {
            if service.name == service_name {
                let service_instances = self.service_to_instance(&service);
                instances.extend(service_instances);
            }
        }

        info!("发现服务 {} 的 {} 个实例", service_name, instances.len());
        Ok(instances)
    }

    async fn health_check(&self, service_name: &str) -> ServiceResult<Vec<ServiceInstance>> {
        // 对于Kubernetes，健康检查与发现服务相同，因为endpoints已经包含了健康状态信息
        self.discover(service_name).await
    }

    async fn watch(&self, service_name: &str) -> ServiceResult<Box<dyn rustcloud_core::ServiceWatcher + Send>> {
        // 简化实现，返回一个空的Watcher
        Ok(Box::new(EmptyWatcher))
    }
}

/// Kubernetes 集成构建器
pub struct K8sIntegrationBuilder {
    client: Option<Arc<KubernetesClient>>,
    config: K8sIntegrationConfig,
}

impl K8sIntegrationBuilder {
    /// 创建新的构建器
    pub fn new() -> Self {
        Self {
            client: None,
            config: K8sIntegrationConfig::default(),
        }
    }

    /// 设置 Kubernetes 客户端
    pub fn with_client(mut self, client: Arc<KubernetesClient>) -> Self {
        self.client = Some(client);
        self
    }

    /// 设置集成配置
    pub fn with_config(mut self, config: K8sIntegrationConfig) -> Self {
        self.config = config;
        self
    }

    /// 设置默认命名空间
    pub fn with_namespace(mut self, namespace: impl Into<String>) -> Self {
        self.config.default_namespace = namespace.into();
        self
    }

    /// 构建服务注册
    pub fn build_service_registry(self) -> K8sResult<Arc<K8sServiceRegistry>> {
        let client = self.client
            .ok_or_else(|| K8sError::config_error("未设置 Kubernetes 客户端"))?;

        let registry = K8sServiceRegistry::new(client, self.config)?;
        Ok(Arc::new(registry))
    }
}

impl Default for K8sIntegrationBuilder {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_integration_config_default() {
        let config = K8sIntegrationConfig::default();
        assert!(config.enable_service_discovery);
        assert_eq!(config.default_namespace, "default");
    }

    #[test]
    fn test_builder_pattern() {
        let builder = K8sIntegrationBuilder::new()
            .with_namespace("test-namespace");
        
        assert_eq!(builder.config.default_namespace, "test-namespace");
    }

    #[test]
    fn test_service_to_instance_conversion() {
        use crate::discovery::{ServiceInfo, ServiceEndpoint};

        let service_info = ServiceInfo {
            name: "test-service".to_string(),
            namespace: "default".to_string(),
            service_type: "ClusterIP".to_string(),
            cluster_ip: Some("10.0.0.1".to_string()),
            external_ips: vec![],
            ports: vec![],
            labels: {
                let mut labels = HashMap::new();
                labels.insert("version".to_string(), "1.0.0".to_string());
                labels
            },
            annotations: HashMap::new(),
            endpoints: vec![
                ServiceEndpoint {
                    ip: "10.0.0.2".to_string(),
                    port: 8080,
                    ready: true,
                    node_name: Some("node-1".to_string()),
                    pod_name: Some("test-pod".to_string()),
                },
            ],
        };

        // 直接测试转换逻辑，不需要实际的Kubernetes客户端
        let mut instances = Vec::new();
        for endpoint in &service_info.endpoints {
            if endpoint.ready {
                let instance = ServiceInstance {
                    service_id: format!("{}:{}:{}", service_info.name, endpoint.ip, endpoint.port),
                    host: endpoint.ip.clone(),
                    port: endpoint.port as u16,
                    scheme: "http".to_string(),
                    metadata: {
                        let mut metadata = service_info.labels.clone();
                        if let Some(pod_name) = &endpoint.pod_name {
                            metadata.insert("pod_name".to_string(), pod_name.clone());
                        }
                        if let Some(node_name) = &endpoint.node_name {
                            metadata.insert("node_name".to_string(), node_name.clone());
                        }
                        metadata
                    },
                    healthy: endpoint.ready,
                    weight: 1.0,
                    group: None,
                    namespace: Some(service_info.namespace.clone()),
                    environment: service_info.labels.get("environment")
                        .or_else(|| service_info.labels.get("env"))
                        .cloned(),
                    cluster: service_info.labels.get("cluster").cloned(),
                };
                instances.push(instance);
            }
        }
        
        assert_eq!(instances.len(), 1);
        
        let instance = &instances[0];
        assert_eq!(instance.service_id, "test-service:10.0.0.2:8080");
        assert_eq!(instance.host, "10.0.0.2");
        assert_eq!(instance.port, 8080);
        assert_eq!(instance.metadata.get("version"), Some(&"1.0.0".to_string()));
    }
}